
//=============================================================================
/**
 *  Composite panel item.
 */
class FCPanelItemComposite : public FCPanelItemBase,
                             public PCL_Interface_Composite<FCPanelItemBase>
{
public:
    /// You must use <B>new</B> to create item and after the item be added, you can't delete it any more.
    BOOL AddItem (FCPanelItemBase* pItem)
    {
        if (!pItem)
            {ASSERT(FALSE); return FALSE;}

        pItem->m_pParentItem = this ;
        PCL_PushObject (pItem) ;
        return TRUE ;
    }

protected:
    /// Constructor.
    FCPanelItemComposite (CWnd* pTopWindow) : FCPanelItemBase(pTopWindow) {}

    /// Load attributes from pElem node.
    void LoadBasicProperty (MSXML::IXMLDOMElementPtr& pElem)
    {
        // load self attributes
        FCPanelItemBase::LoadAttributesFromXML(pElem) ;

        try
        {
            // load children
            MSXML::IXMLDOMElementPtr   pChild = pElem->GetfirstChild() ;
            while (pChild)
            {
                FCPanelItemBase   * pItem = CreateItem (GetTopWindow(), pChild) ;
                // unknow item return NULL, discard
                if (pItem)
                {
                    AddItem (pItem) ;
                    pItem->LoadFrom_MSXML (pChild) ;
                }
                pChild = pChild->GetnextSibling() ;
            }
        }
        catch(_com_error&) {ASSERT(FALSE);}
    }

    /// Save attributes to pElem node.
    void SaveBasicProperty (MSXML::IXMLDOMDocumentPtr& pDoc, MSXML::IXMLDOMElementPtr& pElem)
    {
        // save self attributes
        FCPanelItemBase::SaveAttributesToXML (pElem) ;
        for (int i=0 ; i < PCL_GetObjectCount() ; i++)
            PCL_GetObject(i)->SaveTo_MSXML (pDoc, pElem) ;
    }

    /// Call all children's function.
    virtual void HandleWindowRgnMask (FCObjImage& imgMask32)
    {
        for (int i=0 ; i < PCL_GetObjectCount() ; i++)
            PCL_GetObject(i)->HandleWindowRgnMask(imgMask32) ;
    }

protected:
    // push object's pointer
    virtual void GetFullItemList (std::deque<FCPanelItemBase*>& listItem) const
    {
        listItem.push_back (const_cast<FCPanelItemComposite*>(this)) ;
        for (int i=0 ; i < PCL_GetObjectCount() ; i++)
            PCL_GetObject(i)->GetFullItemList (listItem) ;
    }

    /// Draw all children.
    virtual void OnPaint (CDC* pDC)
    {
        // draw child
        for (int i=0 ; i < PCL_GetObjectCount() ; i++)
        {
            FCPanelItemBase   * pItem = PCL_GetObject(i) ;
            const POINT       ptItem = pItem->GetItemPosition() ;

            // is item visible
            if (!CRect().IntersectRect (CRect(ptItem, pItem->GetItemSize()),
                                        CRect(CPoint(0,0), GetItemSize())))
                continue ;

            CPoint     ptOldView = pDC->OffsetViewportOrg (ptItem.x, ptItem.y) ;
            pItem->OnPaint (pDC) ;
            pDC->SetViewportOrg (ptOldView) ;
        }
    }

    /// Adjust all children size
    virtual void OnSize (CSize NewParentSize, CSize OldParentSize)
    {
        const SIZE   sizeOldItem = GetItemSize() ;

        // must set size/position before call child's OnSize, child maybe call <Item_to_TopWindow>
        CalculateNew (GetItemPosition(), GetItemSize(),
                      NewParentSize, OldParentSize,
                      m_ptItemPos, m_sizeItem) ;
        for (int i=0 ; i < PCL_GetObjectCount() ; i++)
        {
            PCL_GetObject(i)->OnSize (m_sizeItem, sizeOldItem) ;
        }
    }

    // item factory
    FCPanelItemBase* CreateItem (CWnd* pWnd, MSXML::IXMLDOMElementPtr& pElem) ;
};
